const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const { FFMPEG_PATH } = require("./ffmpeg");
const { generateImageToVideoCommand, generateTrimVideoCommand, generateLoopVideoCommand, generatePlaceholderVideoCommand, generateFallbackVideoInfoCommand } = require("./ffmpegCommands");

/**
 * 添加文件和持续时间信息到concat文件内容
 * @param {string} tempDir - 临时目录
 * @param {Object} subtitle - 字幕对象
 * @param {number} index - 索引
 * @param {number} startIndex - 起始索引
 * @param {boolean} shouldAdjustDuration - 是否需要调整时长
 * @param {number} durationScaleFactor - 时长调整因子
 * @returns {string} concat文件内容
 */
function addFileToConcatContent(tempDir, subtitle, index, startIndex, shouldAdjustDuration, durationScaleFactor) {
  const relativeMediaPath = `media_${(index + startIndex).toString().padStart(4, "0")}.mp4`;
  let concatFileContent = `file '${relativeMediaPath}'\n`;

  // 添加duration参数
  let duration = subtitle.duration;
  if (shouldAdjustDuration) {
    duration = subtitle.duration * durationScaleFactor;
  }

  // 确保至少有0.1秒的持续时间，避免过短的帧
  const safeDuration = Math.max(0.1, duration);
  concatFileContent += `duration ${safeDuration}\n`;

  return concatFileContent;
}

/**
 * 处理媒体文件（图片或视频）转换为视频
 * @param {string} currentMedia - 当前媒体文件路径
 * @param {string} mediaOutputPath - 输出视频路径
 * @param {Object} subtitle - 字幕对象
 * @returns {boolean} 是否成功处理
 */
function convertMediaToVideo(currentMedia, mediaOutputPath, subtitle) {
  try {
    console.log(`  检测到图片文件，转换为视频并保持正确宽高比`);
    const convertCommand = generateImageToVideoCommand(currentMedia, mediaOutputPath, subtitle.duration);
    execSync(convertCommand);
    return fs.existsSync(mediaOutputPath);
  } catch (error) {
    console.warn(`  媒体转换失败: ${error.message}`);
    return false;
  }
}

/**
 * 获取视频时长
 * @param {string} videoPath - 视频文件路径
 * @returns {number|null} 视频时长（秒）
 */
function getVideoDuration(videoPath) {
  try {
    const ffmpegCommand = generateFallbackVideoInfoCommand(videoPath);
    console.log(`  执行ffmpeg命令获取时长: ${ffmpegCommand}`);
    const ffmpegOutput = execSync(ffmpegCommand, { encoding: "utf8" });
    // console.log(`  ffmpeg输出: ${ffmpegOutput}`);
    const durationMatch = ffmpegOutput.match(/Duration: (\d{2}:\d{2}:\d{2}\.\d{2})/);
    if (durationMatch) {
      const timeParts = durationMatch[1].split(":");
      return parseFloat(timeParts[0]) * 3600 + parseFloat(timeParts[1]) * 60 + parseFloat(timeParts[2]);
    } else {
      throw new Error("Could not extract duration from ffmpeg output");
    }
  } catch (fallbackError) {
    console.error(`！！！无法获取视频时长信息: ${videoPath}`, fallbackError.message);
    return null;
  }
}

/**
 * 处理视频文件，根据字幕时长调整视频片段
 * @param {string} videoPath - 视频文件路径
 * @param {number} subtitleDuration - 字幕持续时间（秒）
 * @param {string} outputDir - 输出目录
 * @param {string} outputName - 输出文件名
 * @returns {string} 处理后的视频文件路径
 */
function processVideoForDuration(videoPath, subtitleDuration, outputDir, outputName) {
  try {
    console.log(`  处理视频文件: ${videoPath}, 目标时长: ${subtitleDuration}`);
    const outputPath = path.join(outputDir, outputName);

    // 获取视频信息
    const videoDuration = getVideoDuration(videoPath) || subtitleDuration * 1.5;
    console.log(`  使用视频时长: ${videoDuration} seconds`);

    // 如果视频时长小于字幕时长，循环播放视频
    if (videoDuration < subtitleDuration) {
      console.log(`  视频时长小于字幕时长，需要循环播放`);
      const repeatCount = Math.ceil(subtitleDuration / videoDuration);
      const fileListPath = path.join(outputDir, `repeat_${outputName}.txt`);

      // 创建包含重复视频条目的列表文件
      let fileContent = "";
      for (let i = 0; i < repeatCount; i++) {
        fileContent += `file '${videoPath.replace(/\\/g, "/")}'\n`;
      }

      fs.writeFileSync(fileListPath, fileContent);

      // 使用concat demuxer合并视频
      const concatCommand = `"${FFMPEG_PATH}" -y -loglevel quiet -f concat -safe 0 -i "${fileListPath}" -c copy "${outputPath}_temp.mp4"`;
      console.log(`  执行concat命令: ${concatCommand}`);
      execSync(concatCommand);

      // 裁剪到精确的字幕时长
      const loopCommand = generateLoopVideoCommand(`${outputPath}_temp.mp4`, outputPath, subtitleDuration);
      console.log(`  执行loop命令: ${loopCommand}`);
      execSync(loopCommand);

      // 删除临时文件
      try {
        if (fs.existsSync(`${outputPath}_temp.mp4`)) {
          fs.unlinkSync(`${outputPath}_temp.mp4`);
        }
        if (fs.existsSync(fileListPath)) {
          fs.unlinkSync(fileListPath);
        }
      } catch (error) {
        console.warn(`清理临时文件时出错: ${error.message}`);
      }
    }
    // 如果视频时长足够，从中间部分截取合适片段
    else {
      console.log(`  视频时长足够，从中截取片段`);
      const startTime = (videoDuration - subtitleDuration) / 2;
      // 保持正确的宽高比
      const trimCommand = generateTrimVideoCommand(videoPath, outputPath, startTime, subtitleDuration);
      // console.log(`  执行trim命令: ${trimCommand}`);
      console.log(`  执行trim命令...`);
      execSync(trimCommand);
    }

    // 检查输出文件是否存在
    if (fs.existsSync(outputPath)) {
      console.log(`  视频处理完成: ${outputPath}`);
      return outputPath;
    } else {
      console.error(`！！！视频处理失败，输出文件不存在: ${outputPath}`);
      return null;
    }
  } catch (error) {
    console.error(`！！！处理视频文件时出错: ${error.message}`);
    return null;
  }
}

/**
 * 处理媒体文件（图片或视频）
 * @param {string} currentMedia - 当前媒体文件路径
 * @param {Object} subtitle - 字幕对象
 * @param {string} tempDir - 临时目录
 * @param {number} index - 索引
 * @param {number} startIndex - 起始索引
 * @param {boolean} shouldAdjustDuration - 是否需要调整时长
 * @param {number} durationScaleFactor - 时长调整因子
 * @returns {Object} 包含文件内容和时长的对象
 */
function processMediaFile(currentMedia, subtitle, tempDir, index, startIndex, shouldAdjustDuration, durationScaleFactor) {
  let concatFileContent = "";
  // 获取媒体文件扩展名
  const fileExt = path.extname(currentMedia).toLowerCase();
  const isVideo = [".mp4", ".mov", ".avi", ".mkv"].includes(fileExt);

  // 统一输出为mp4格式，确保所有媒体都是视频格式
  const mediaOutputPath = path.join(tempDir, `media_${(index + startIndex).toString().padStart(4, "0")}.mp4`);

  // 处理媒体文件
  if (fs.existsSync(currentMedia)) {
    console.log(`  开始处理媒体文件: ${currentMedia}`);
    try {
      if (isVideo) {
        // 处理视频文件
        console.log(`  检测到视频文件，使用processVideoForDuration`);
        const processedVideo = processVideoForDuration(currentMedia, subtitle.duration, tempDir, `media_${(index + startIndex).toString().padStart(4, "0")}.mp4`);

        if (processedVideo && fs.existsSync(processedVideo)) {
          console.log(`  视频处理成功: ${processedVideo}`);
          concatFileContent += addFileToConcatContent(tempDir, subtitle, index, startIndex, shouldAdjustDuration, durationScaleFactor);
        } else {
          // 如果视频处理失败，回退到将原始文件转换为视频
          console.warn(`  视频处理失败，回退到图片转换方式`);
          if (convertMediaToVideo(currentMedia, mediaOutputPath, subtitle)) {
            concatFileContent += addFileToConcatContent(tempDir, subtitle, index, startIndex, shouldAdjustDuration, durationScaleFactor);
          }
        }
      } else {
        // 处理图片文件，保持正确的宽高比
        if (convertMediaToVideo(currentMedia, mediaOutputPath, subtitle)) {
          concatFileContent += addFileToConcatContent(tempDir, subtitle, index, startIndex, shouldAdjustDuration, durationScaleFactor);
        }
      }
    } catch (convertError) {
      console.warn(`媒体文件处理失败: ${currentMedia}`, convertError.message);
      // 如果处理失败，创建一个纯色视频作为占位符
      try {
        const placeholderCommand = generatePlaceholderVideoCommand(mediaOutputPath, subtitle.duration);
        execSync(placeholderCommand);

        if (fs.existsSync(mediaOutputPath)) {
          concatFileContent += addFileToConcatContent(tempDir, subtitle, index, startIndex, shouldAdjustDuration, durationScaleFactor);
        }
      } catch (placeholderError) {
        console.error(`！！！创建占位符视频失败: ${currentMedia}`, placeholderError.message);
      }
    }
  }

  return concatFileContent;
}

module.exports = {
  getVideoDuration,
  processVideoForDuration,
  processMediaFile,
  addFileToConcatContent,
};
